﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Renci.iRods.Common;
using System.Collections.ObjectModel;

namespace Renci.iRods.Packets
{
    //#define GenQueryInp_PI "int maxRows; int continueInx; int partialStartIndex; int options; struct KeyValPair_PI; struct InxIvalPair_PI; struct InxValPair_PI;"
    [Packet("GenQueryInp_PI")]
    internal class GeneralQueryInputPacket : Packet
    {
        /// <summary>
        /// Gets or sets the maximum number of rows to return, if 0 close out the SQL statement call (i.e. instead of getting more rows until it is finished).
        /// </summary>
        /// <value>
        /// The maximum rows.
        /// </value>
        [PacketField("maxRows", 0, DataTypes.Int)]
        public int MaximumRows { get; private set; }

        /// <summary>
        /// If non-zero, this is the value returned in the genQueryOut structure and the current call is to get more rows.
        /// In this case, the selectInp & sqlCondInp arguments are ignored.
        /// </summary>
        /// <value>
        /// The index of the continue.
        /// </value>
        [PacketField("continueInx", 1, DataTypes.Int)]
        public int QueryExecutionID { get; internal set; }

        /// <summary>
        /// Gets or sets the partial index of the start. 
        /// If positive, return rows starting with this index (skip earlier ones), 0-origin.
        /// </summary>
        /// <value>
        /// The partial index of the start.
        /// </value>
        [PacketField("partialStartIndex", 2, DataTypes.Int)]
        public int PartialStartIndex { get; private set; }

        /// <summary>
        /// Gets or sets the options.
        ///  Bits for special options, currently: 
        ///  If RETURN_TOTAL_ROW_COUNT is set, 
        ///  the total number of available rows will be returned in totalRowCount (causes a little overhead so only request it if needed).  
        ///  If rowOffset is also used, totalRowCount will include the skipped rows. 
        ///  If NO_DISTINCT is set, the normal 'distinct' keyword is not included in the SQL query. 
        ///  If QUOTA_QUERY is set, do the special quota query.
        /// </summary>
        /// <value>
        /// The options.
        /// </value>
        [PacketField("options", 3, DataTypes.Int)]
        public int Options { get; set; }

        [PacketField("KeyValPair_PI", 4, DataTypes.Packet)]
        public KeyValuePairPacket ConditionInput { get; private set; }

        [PacketField("InxIvalPair_PI", 5, DataTypes.Packet)]
        public IntegerValuePairPacket SelectedColumns { get; private set; }

        [PacketField("InxValPair_PI", 6, DataTypes.Packet)]
        public IndexValuePairPacket WhereConditions { get; private set; }

        public GeneralQueryInputPacket(IDictionary<DataObjectAttributes, QueryColumnAction> columns, IDictionary<DataObjectAttributes, string> conditions, int takeRows, int skipRows, IRodsQueryOption options)
        {
            this.MaximumRows = takeRows;
            this.PartialStartIndex = skipRows;
            this.SelectedColumns = new IntegerValuePairPacket(columns);
            this.WhereConditions = new IndexValuePairPacket(conditions);
            this.ConditionInput = new KeyValuePairPacket(new Dictionary<string, string>());
            this.Options = (int)options;
        }

        public GeneralQueryInputPacket(IDictionary<DataObjectAttributes, QueryColumnAction> columns, IDictionary<DataObjectAttributes, string> conditions, int executionId, int takeRows, int skipRows, IRodsQueryOption options)
            : this(columns, conditions,takeRows, skipRows, options)
        {
            this.QueryExecutionID = executionId;
        }
    }
}
